
use std::fmt::{self, Formatter, Display};

// #[allow(dead_code)]
#[derive(Debug)]
struct Structure(i32);

impl Display for Structure{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "--({})--", self.0)
    }
}

#[derive(Debug)]
struct Deep(Structure);

#[derive(Debug)]
struct Person<'a> {
    name: &'a str,
    age: u8
}

pub fn print_test_01(){
    println!("格式化打印测试(print_test_01)====>");

    println!("一般打印 {{}} {} days", 31);
    println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob");
    println!("{subject} {verb} {object}",
                 object="the lazy dog",
                 subject="the quick brown fox",
                 verb="jumps over");
    println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
    println!("{number:>width$}", number=1, width=6); // 打印1宽度6
    println!("{number:>0width$}", number=1, width=6); //打印1，0宽度6
    println!("My name is {0}, {1} {0}", "Bond", "Alice"); // 没有{1}对应值, 

    // fmt::Debug: Uses the {:?} marker. // 实现了Debug特性可用{:?}标记打印信息
    // fmt::Display: Uses the {} marker. // 实现了display特性可用{}打印信息
    println!("This struct `{}` won't print...", Structure(3)); //
    println!("{{:#?}}打印 {:#?}", Deep(Structure(5))); // 打印deep
    println!("{1:?} {0:?} is the {actor:?} name.",  // {1:?} 打印第二个 数组标记法
                 "Slater",
                 "Christian",
                 actor="actor's"); // 打印名字标记法
    let name = "Peter";
    let age = 27;
    let peter = Person { name, age };
    println!("{:#?}", peter); // 漂亮打印？

    let v = List(vec![1, 2, 3]);
    println!("测试打印列表的，循环实现了display特性（trait）打印列表值  {}", v);

    let foo = 3735928559i64;
    format!("打印 {{}} {}", foo); // -> "3735928559"
    format!("打印 0x{{:X}} : 0x{:X}", foo); // -> "0xDEADBEEF"
    format!("打印 0o{{:o}} : 0o{:o}", foo); // -> "0o33653337357"
    
    test_format();
}

// Define a structure named `List` containing a `Vec`.
pub struct List(Vec<i32>);// 这个结构有个vec的列表list

impl fmt::Display for List { // 列表要display
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Extract the value using tuple indexing
        // and create a reference to `vec`.
        let vec = &self.0;

        write!(f, "[")?;

        // Iterate over `vec` in `v` while enumerating the iteration
        // count in `count`.
        for (count, v) in vec.iter().enumerate() {
            // For every element except the first, add a comma.
            // Use the ? operator, or try!, to return on errors.
            if count != 0 { write!(f, ", ")?; }
            write!(f, "{}: {}", count, v)?;
        }

        // Close the opened bracket and return a fmt::Result value
        write!(f, "]")
    }
}

struct City {
    name: &'static str,
    // Latitude
    lat: f32,
    // Longitude
    lon: f32,
}

impl Display for City {
    // `f` is a buffer, this method must write the formatted string into it
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' };
        let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' };

        // `write!` is like `format!`, but it will write the formatted string
        // into a buffer (the first argument)
        write!(f, "{}: {:.3}°{} {:.3}°{}",
               self.name, self.lat.abs(), lat_c, self.lon.abs(), lon_c)
    }
}

#[derive(Debug)]
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

fn test_format() {
    for city in [
        City { name: "Dublin", lat: 53.347778, lon: -6.259722 },
        City { name: "Oslo", lat: 59.95, lon: 10.75 },
        City { name: "Vancouver", lat: 49.25, lon: -123.1 },
    ].iter() {
        println!("{}", *city);
    }
    for color in [
        Color { red: 128, green: 255, blue: 90 },
        Color { red: 0, green: 3, blue: 254 },
        Color { red: 0, green: 0, blue: 0 },
    ].iter() {
        // Switch this to use {} once you've added an implementation
        // for fmt::Display
        println!("{:?}", *color);
    }
}